#include <math.h>
#include <stdlib.h>
#include <GL/glut.h>

#include <stdio.h>
#include <stdarg.h> // for va_array va_start, va_end
#include <string.h> // for strlen

#include "fonts.c"

//#define M_PI 3.14159265

// Todo: glSetTex, glRemoveTex

static int numframes = 0;
static int xres, yres;
static float moveToX, moveToY;
static float mousx, mousy;
static int bstatus;
static int keystatus[256];

static void draw(); // fwd decl
static void init(); // fwd decl

void HandleMouse(int,int,int,int);
void reshape(int width, int height);


static void moveTo(float x, float y)
{
    moveToX = x;
    moveToY = y;
}
static void lineTo(float x, float y)
{
    glBegin(GL_LINES);
        glVertex2f(moveToX, moveToY);
        glVertex2f(x,y);
    glEnd();
    moveToX = x;
    moveToY = y;
}

static void drawSph(float x, float y, float radi)
{
    if(radi < 0)
    {
        radi*=-1;
        glBegin(GL_LINE_LOOP);
    } else{
        glBegin(GL_POLYGON);
    }
    int segs = 18;
    // increase segments with radius
    if( fabs(radi) > 50) segs += 6;
    if( fabs(radi) > 150) segs += 9;
    
    int i;
    for(i=0; i<segs; i++)
    {
        glVertex2f(x+cos(i*2*M_PI/segs)*radi, y+sin(i*2*M_PI/segs)*radi );
    }
    glEnd();   
}

static float rnd()
{
    return (float)rand() / (float)RAND_MAX;
}

// how do i normalize rnd?
static float nrnd()
{
    return 1.0f-(float)rand() / ((float)RAND_MAX/2);
}


/* new window size or exposure */
void reshape(int width, int height)
{
    xres = width;
    yres = height;

    glViewport( 0, 0, width, height );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho( 0.0, width, height, 0.0, -1.0, 1.0 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity(); 
}

static void idle(void)
{ 
  glutPostRedisplay();
}

float klock()
{
    return (float) glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
}

void visible(int vis)
{
  if (vis == GLUT_VISIBLE)
  {
    //glutIdleFunc(idle);
  }
  else
  {
    //glutIdleFunc(NULL); // dont draw if minimized.
  }
}

// no release callback :(
// freeglut has, use it instead!
static void key(unsigned char k, int x, int y)
{        
  keystatus[k] = !keystatus[k];
  glutPostRedisplay();
}

static void special(int k, int x, int y)
{
}
  
void glPrintf(const char *format,...)
{
    va_list args;
    char buffer[200], *p;

    va_start(args, format);
    vsprintf(buffer, format, args);
    va_end(args);

    bitmap_output( (int)moveToX, (int)moveToY, buffer,
        GLUT_BITMAP_9_BY_15);
}

/*
   Handle mouse events
*/
void HandleMouse(int button,int state,int x,int y)
{
    if (state == GLUT_DOWN)
    {
        if (button == GLUT_LEFT_BUTTON) bstatus = bstatus | 1;
        if (button == GLUT_MIDDLE_BUTTON) bstatus = bstatus | 4;
        if (button == GLUT_RIGHT_BUTTON)  bstatus = bstatus | 2;
    } 
    if (state == GLUT_UP) 
    {
        if (button == GLUT_LEFT_BUTTON) bstatus = bstatus & ~1;
        if (button == GLUT_MIDDLE_BUTTON) bstatus = bstatus & ~4;
        if (button == GLUT_RIGHT_BUTTON)  bstatus = bstatus & ~2;        
    }
}
void HandleMouseMotion(int x, int y)
{
    mousx = x;
    mousy = y;
    glutPostRedisplay();
}

int main(int argc, char *argv[])
{
    int w = 640; int h = 480;
    xres = w;
    yres = h;
    
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);

    glutInitWindowPosition(0, 0);
    glutInitWindowSize(w, h);
    glutCreateWindow("glSimple");
    glutDisplayFunc(draw);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(key);
    //glutKeyboardUpFunc(key); // add gameglut, freeglut or openglut for this.
    glutSpecialFunc(special);
    glutMouseFunc(HandleMouse);
    glutMotionFunc(HandleMouseMotion);
    glutPassiveMotionFunc(HandleMouseMotion); 
    glutVisibilityFunc(visible); 
    glutIdleFunc(idle);
    

    int i=0;
    for(i=0; i<256; i++)
        keystatus[i] = 0;
        
    init();
    glutMainLoop();
    return 0;
}
